/**
 * 版权所有 @鸿名物联
 * 未经授权，禁止侵权和商业，违法必究
 * 联系QQ：2224313811
 */
package com.lp.controller.iot;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.lp.bo.*;
import com.lp.cache.CacheName;
import com.lp.cache.ProCacheUtil;
import com.lp.cfg.ProConfig;
import com.lp.common.Code;
import com.lp.common.Code.ResponseCode;
import com.lp.common.CodeIot;
import com.lp.common.Constants;
import com.lp.common.RequestURLIOT;
import com.lp.controller.BaseController;
import com.lp.dao.BaseDao;
import com.lp.listener.DeviceImportListener;
import com.lp.service.IotNodeInfoService;
import com.lp.util.ObjectUtil;
import com.lp.util.PageBean;
import com.lp.util.ResultMapUtils;
import com.lp.util.iot.ProtocolUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Controller
public class IotNodeInfoController extends BaseController {

    @Autowired
    private IotNodeInfoService iotNodeInfoService;
    @Autowired
    @Qualifier("baseDao")
    protected BaseDao dao;

    /**
     * 检索
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO_PAGE)
    public ModelAndView selectPage(HttpServletResponse response,
                                   @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                   @RequestBody IotNodeInfoBO obj,
                                   @RequestParam(required = false) Integer pageSize,
                                   @RequestParam Integer paged) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            obj.setUser_id(user.getId());
            //普通用户
            if (user.getType() == 7) {
                obj.setCustom_id(obj.getUser_id());
            }
            resultMap = service.selectPageList("IotNodeInfo.selectPage", getPageBean(paged, pageSize), obj);
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 设备统计
     *
     * @param response
     * @param userKey
     * @param obj
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_STATISTIC)
    public ModelAndView selectStatisticNode(HttpServletResponse response,
                                            @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                            @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            obj.setUser_id(user.getId());
            resultMap = service.selectList("IotNodeInfo.selectStatisticNodeInfo", obj);
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 检索 - 管理员使用
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.ADMIN_NODE_INFO_PAGE)
    public ModelAndView selectALLNodePage(HttpServletResponse response,
                                          @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                          @RequestBody IotNodeInfoBO obj,
                                          @RequestParam(required = false) Integer pageSize,
                                          @RequestParam Integer paged) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            if (user.getType() == Code.UserType.SUPER) {
                resultMap = service.selectPageList("IotNodeInfo.selectPage", getPageBean(paged, pageSize), obj);
            }
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 设备仓库
     * 未使用设备
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.ADMIN_UNUSED_NODES)
    public ModelAndView selectALLUnusedDevice(HttpServletResponse response,
                                              @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                              @RequestBody IotNodeInfoBO obj,
                                              @RequestParam(required = false) Integer pageSize,
                                              @RequestParam Integer paged) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            if (user.getType() == Code.UserType.SUPER) {
                resultMap = service.selectPageList("IotNodeInfo.selectUnUsedNode", getPageBean(paged, pageSize), obj);
            }
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 插入
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO)
    public ModelAndView save(HttpServletResponse response,
                             @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                             @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            if (ObjectUtil.isNotEmpty(obj.getScene_id())) {
                IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code());
                // 判断device_code是否重复
                if (ObjectUtil.isNotEmpty(nodeInfo)) {
                    putStatusCode(resultMap, ResponseCode.IotInfo.DEVICE_CODE_EXIST);
                } else {
                    obj.setIot_node_status(CodeIot.DEVICE_STATUS.UNCONTECT);
                    obj.setMtime(new Date());
                    resultMap = iotNodeInfoService.saveNodeInfo(obj);
                }
            } else {
                putStatusCode(resultMap, ResponseCode.SystemCode.PARAM_ERROR);
            }
            if (isOk(resultMap)) {
                ProCacheUtil.addCache(CacheName.NODEINFO, obj.getId().toString(), obj);
                ProCacheUtil.addCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code(), obj);
            }
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 网关下数据的同步
     */
    @RequestMapping(method = RequestMethod.PUT, value = RequestURLIOT.NodeInfo.NODE_DATA_INFO_SYNC)
    public ModelAndView syncNodeStatus(HttpServletResponse response,
                                       @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            resultMap = iotNodeInfoService.syncData(obj);
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 根据设备仓库中的设备号添加
     *
     * @param response
     * @param userKey
     * @param obj
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_BIND)
    public ModelAndView deviceAdd(HttpServletResponse response,
                                  @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                  @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            if (ObjectUtil.isNotEmpty(obj.getDevice_code()) && ObjectUtil.isNotEmpty(obj.getScene_id())) {
                //
                IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code());
                if (ObjectUtil.isNotEmpty(nodeInfo)) {
                    //
                    if (nodeInfo.getScene_id() != null) {
                        // 设备码已使用
                        putStatusCode(resultMap, Code.ResponseCode.IotInfo.DEVICE_CODE_USED);
                    } else {
                        obj.setId(nodeInfo.getId());
                        // id , scene_id  , device_code
                        resultMap = service.update("IotNodeInfo.update", obj);
                        if (isOk(resultMap)) {
                            nodeInfo.setScene_id(obj.getScene_id());
                        }
                    }
                } else {
                    // 设备码不存在
                    putStatusCode(resultMap, Code.ResponseCode.IotInfo.DEVICE_CODE_NOT_EXIST);
                    ;
                }
            } else {
                putStatusCode(resultMap, Code.ResponseCode.SystemCode.PARAM_ERROR);
            }
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * app端用户绑定设备
     *
     * @param response
     * @param userKey
     * @param deviceBindBO
     * @return
     */

    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.WX_NODE_BIND)
    @Transactional(rollbackFor = Exception.class)
    public ModelAndView deviceBindByApp(HttpServletRequest request, HttpServletResponse response,
                                        @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                        @RequestBody DeviceBindBO deviceBindBO) {
        PageBean pageBean = new PageBean();
        pageBean.setPaged(1);
        pageBean.setPageSize(Integer.MAX_VALUE);
        UserInfoBO user = getUserInfoByUserKey(userKey);
        IotNodeInfoBO obj = new IotNodeInfoBO();
        Map<String, Object> resultMap = getResultMap();
        try {
            if (ObjectUtil.isNotEmpty(deviceBindBO.getDevice_code())) {
                IotNodeInfoBO nodeInfo = ProCacheUtil.getCache(CacheName.NODEINFO_DEVICECODE, deviceBindBO.getDevice_code());
//						判断上级经销商识别码存在且该设备处在该经销商设备目录下
                //查询经销商是否存在
                UserInfoBO userInfoBO = new UserInfoBO();
                userInfoBO.setName(deviceBindBO.getUserName());
                List<UserInfoBO> userList = dao.selectList("UserInfo.select", userInfoBO, pageBean);
                if (userList.size() == 0) {
                    //经销商不存在
                    putStatusCode(resultMap, Code.ResponseCode.UserInfo.USER_NOT_EXISTS);
                } else {
                    //查询经销商项目
                    IotSceneInfoBO iotSceneInfoBO = new IotSceneInfoBO();
                    iotSceneInfoBO.setUser_id(userList.get(0).getId());
                    List<IotSceneInfoBO> sceneList = dao.selectList("IotSceneInfo.selectSceneInfo", iotSceneInfoBO, pageBean);
                    //查询设备所在项目
                    obj.setDevice_code(deviceBindBO.getDevice_code());
                    List<IotNodeInfoBO> iotNodeInfoList = dao.selectList("IotNodeInfo.selectPage", obj, pageBean);
                    if (iotNodeInfoList.size() == 0) {
                        //设备所在项目不存在
                        putStatusCode(resultMap, Code.ResponseCode.SystemCode.NO_DATA);
                    } else {
                        if (!sceneList.stream().anyMatch(scene -> scene.getId().equals(iotNodeInfoList.get(0).getScene_id()))) {
                            //绑定的设备不在经销商下
                            putStatusCode(resultMap, Code.ResponseCode.SystemCode.NO_DATA);
                        } else {
                            if (ObjectUtil.isNotEmpty(nodeInfo)) {
                                if (nodeInfo.getCustom_id() != null) {
                                    // 设备码已绑定用户
                                    putStatusCode(resultMap, Code.ResponseCode.IotInfo.DEVICE_CODE_BIND);
                                } else {
                                    obj.setId(nodeInfo.getId());
                                    obj.setDevice_code(deviceBindBO.getDevice_code());
                                    obj.setCustom_id(user.getId());
                                    resultMap = service.update("IotNodeInfo.update", obj);
                                    if (isOk(resultMap)) {
                                        nodeInfo.setScene_id(obj.getScene_id());
                                        //绑定项目
                                        IotSceneUserRelationBO iotSceneUserRelationBO = new IotSceneUserRelationBO();
                                        iotSceneUserRelationBO.setScene_id(iotNodeInfoList.get(0).getScene_id());
                                        iotSceneUserRelationBO.setUser_id(user.getId());
                                        List<IotSceneUserRelationBO> iotSceneUserRelationBOList = dao.selectList("IotSceneUserRelation.select", iotSceneUserRelationBO, pageBean);
                                        if (iotSceneUserRelationBOList.size() == 0) {
                                            iotSceneUserRelationBO.setAid(iotSceneInfoBO.getUser_id());
                                            dao.insert("IotSceneUserRelation.insert", iotSceneUserRelationBO);
                                        }

                                        //绑定经销商
                                        return UserSettingSub(response, user, deviceBindBO.getUserName());
                                    }
                                }

                            } else {
                                // 设备码不存在
                                putStatusCode(resultMap, Code.ResponseCode.IotInfo.DEVICE_CODE_NOT_EXIST);
                            }
                        }
                    }
                }

            } else {
                putStatusCode(new HashMap<String, Object>(), Code.ResponseCode.SystemCode.PARAM_ERROR);
            }
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    private ModelAndView UserSettingSub(HttpServletResponse response, UserInfoBO user, String userName) {
        Map<String, Object> resultMap = getResultMap();
        try {
            if (ObjectUtil.isEmpty(user.getName())) {
                putStatusCode(new HashMap<String, Object>(), Code.ResponseCode.SystemCode.PARAM_ERROR);
            } else {
                UserInfoBO userInfo = new UserInfoBO();
                userInfo.setDelete_flag(Constants.DELETE.NO);
                userInfo.setName(user.getName());
                resultMap = service.selectOne("UserInfo.selectOne", userInfo);
                userInfo = getData(resultMap);
                //查询经销商用户id
                UserInfoBO userInfo2 = new UserInfoBO();
                userInfo2.setDelete_flag(Constants.DELETE.NO);
                userInfo2.setName(userName);
                resultMap = service.selectOne("UserInfo.selectOne", userInfo2);
                userInfo2 = getData(resultMap);
                if (isOk(resultMap) && (userInfo.getAid() == null || userInfo.getAid() == -1 || userInfo.getAid() == userInfo2.getId())) {
                    UserInfoBO mainUserInfo = new UserInfoBO();
                    mainUserInfo.setDelete_flag(Constants.DELETE.NO);
                    mainUserInfo.setName(userName);
                    resultMap = service.selectOne("UserInfo.selectOne", mainUserInfo);
                    mainUserInfo = getData(resultMap);
                    if (ObjectUtil.isNotEmpty(mainUserInfo)) {
                        // 更新
                        UserInfoBO user1 = new UserInfoBO();
                        user1.setId(userInfo.getId());
                        user1.setAid(mainUserInfo.getId());
                        service.update("UserInfo.updateAid", user1);
                    }
                } else {
                    //用户已绑定其他经销商
                    putStatusCode(new HashMap<String, Object>(), Code.ResponseCode.SystemCode.PARAM_ERROR);
                }
            }
        } catch (Exception e) {
            exception(e, resultMap, userName);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 查询单个
     *
     * @param response
     * @param id
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = RequestURLIOT.NodeInfo.NODE_INFO)
    public ModelAndView selectOne(HttpServletResponse response,
                                  @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                  @RequestParam Integer id) {
        Map<String, Object> resultMap = getResultMap();
        try {

            resultMap = service.selectOne("IotNodeInfo.selectOne", new IotNodeInfoBO(id));
        } catch (Exception e) {
            exception(e, resultMap, id);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * LPM 更新网关状态，设备在线
     *
     * @param response
     * @param obj
     * @return
     */
    @RequestMapping(method = RequestMethod.PUT, value = RequestURLIOT.NodeInfo.NODE_STATUS_INFO)
    public ModelAndView updateNodeStatus(HttpServletResponse response,
                                         @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            resultMap = iotNodeInfoService.updateNodeStatus(obj);
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 更新
     *
     * @param response
     * @param obj
     * @return
     */
    @RequestMapping(method = RequestMethod.PUT, value = RequestURLIOT.NodeInfo.NODE_INFO)
    public ModelAndView update(HttpServletResponse response,
                               @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                               @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            if (!verifyUserRole(userKey, Code.UserType.SUPER)) {
                obj.setUser_id(user.getId());
            }
            resultMap = service.update("IotNodeInfo.update", obj);
            // 更新网关下传感器的经纬度数值
            IotSensorInfoBO iotSensorInfoBo = new IotSensorInfoBO();
            iotSensorInfoBo.setNode_id(obj.getId());
            iotSensorInfoBo.setIot_sensor_type(CodeIot.SENSOR_TYPE.POSITION);
            iotSensorInfoBo.setStr_sdata(obj.getLonLat());
            service.update("IotSensorInfo.updateSensorBySelf", iotSensorInfoBo);
            if (isOk(resultMap)) {
                // 更新device
                IotNodeInfoBO pre = ProCacheUtil.getCache(CacheName.NODEINFO, obj.getId().toString());
                ProCacheUtil.addCache(CacheName.NODEINFO, obj.getId().toString(), obj);
                if (ObjectUtil.isEmpty(obj.getDevice_code())) {
                    // 这边是迁移设备到其他项目中
                    pre.setScene_id(obj.getScene_id());
                } else {
                    if (pre.getDevice_code().equals(obj.getDevice_code())) {
                        ProCacheUtil.addCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code(), obj);
                    } else {
                        ProCacheUtil.addCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code(), obj);
                        ProCacheUtil.removeCache(CacheName.NODEINFO_DEVICECODE, pre.getDevice_code());
                    }

                    if (obj.getIot_node_type() + 0 == 83) {
                        // 修改网关信息后，则设置设备重新连接  TCP协议
                        ProtocolUtil.sendGatewayRestart(obj);
                    }
                }
            }
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 设备excel导入
     */
    @RequestMapping(method = RequestMethod.POST, value = "/node/upload")
    public ModelAndView upload(HttpServletResponse response,
                               @RequestParam(required = false, value = "type") String type,
                               @RequestParam(required = false, value = "property") String[] property,
                               @RequestParam(required = false, value = "file") MultipartFile file) {
        Map<String, Object> resultMap = getResultMap();
        try {
            resultMap = iotNodeInfoService.importTemplateNodeInfo(file);
        } catch (Exception e) {
            super.exception(e, resultMap, file);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 检索设备下的传感器列表，这个是全部检索，没有分页功能
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO_SENSOR_INFO_PAGE)
    public ModelAndView selectNodeSensorListPage(HttpServletResponse response,
                                                 @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                                 @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            obj.setUser_id(user.getId());

            resultMap = service.selectList("IotNodeInfo.selectNodeSensorList", obj);

        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 增加设备列表，支持分页
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO_SENSOR_INFO_PAGES)
    public ModelAndView selectNodeSensorListPages(HttpServletResponse response,
                                                  @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                                  @RequestParam(required = false) Integer pageSize,
                                                  @RequestParam Integer paged,
                                                  @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            UserInfoBO user = getUserInfoByUserKey(userKey);
            obj.setUser_id(user.getId());
            //普通用户
            if (user.getType() == 7) {
                obj.setCustom_id(obj.getUser_id());
            }
            resultMap = service.selectPageList("IotNodeInfo.selectNodeSensorList", getPageBean(paged, pageSize), obj);
        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 删除
     *
     * @param response
     * @param id
     * @return
     */
    @RequestMapping(method = RequestMethod.DELETE, value = RequestURLIOT.NodeInfo.NODE_INFO)
    public ModelAndView delete(HttpServletResponse response,
                               @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                               @RequestParam Integer id) {
        Map<String, Object> resultMap = getResultMap();
        try {
            IotNodeInfoBO obj = new IotNodeInfoBO();
            if (ObjectUtil.isEmpty(id)) {
                putStatusCode(resultMap, Code.ResponseCode.SystemCode.PARAM_ERROR);
            } else {
                UserInfoBO user = getUserInfoByUserKey(userKey);
                if (!verifyUserRole(userKey, Code.UserType.SUPER)) {
                    obj.setUser_id(user.getId());
                }
                obj.setId(id);
                resultMap = service.delete("IotNodeInfo.deleteNode", obj);
                if (isOk(resultMap)) {

                    // 这边再删除sensorlist 信息
                    IotSensorInfoBO sensorBo = new IotSensorInfoBO();
                    sensorBo.setNode_id(id);
                    List<IotSensorInfoBO> sensors = getData(service.selectList("IotSensorInfo.select", sensorBo));
                    if (ObjectUtil.isNotEmpty(sensors)) {
                        for (IotSensorInfoBO t : sensors) {
                            ProCacheUtil.removeCache(CacheName.SENSORINFO, t.getId() + "");
                            ProCacheUtil.removeCache(CacheName.SENSORINFO_NSP, id + "-" + t.getSensor_device_id() + "-" + t.getPort_id());
                        }
                        // 删除所有传感器
                        service.delete("IotSensorInfo.deleteSensorByNodeId", sensorBo);
                    }

                    // obj 获取缓存
                    obj = ProCacheUtil.getCache(CacheName.NODEINFO, obj.getId().toString());
                    ProCacheUtil.removeCache(CacheName.NODEINFO, obj.getId().toString());
                    ProCacheUtil.removeCache(CacheName.NODEINFO_DEVICECODE, obj.getDevice_code());
                }
            }
        } catch (Exception e) {
            exception(e, resultMap, id);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 储存该设备下，设备的所有数据
     *
     * @param response
     * @param userKey
     * @param id
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, value = RequestURLIOT.NodeInfo.NODE_DATA_SAVE)
    public ModelAndView saveNodeData(HttpServletResponse response,
                                     @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                     @RequestParam Integer id) {
        Map<String, Object> resultMap = getResultMap();
        try {
            // 不储存设备数据
            if (!"1".equals(ProConfig.APP_NODE_DATA_SAVE)) {
                return getModelAndView(response, resultMap);
            }
            //
            IotSensorInfoBO sensorBo = new IotSensorInfoBO();
            sensorBo.setNode_id(id);
            resultMap = service.selectList("IotSensorInfo.selectSensorList", sensorBo);
            if (isOk(resultMap)) {
                List<IotSensorInfoBO> sensorList = getData(resultMap);
                String ids = "", values = "";
                for (IotSensorInfoBO t : sensorList) {
                    ids += "|" + t.getId();
                    values += "|" + t.getSdata();
                }
                IotHistoryNodeDataBO nodeDataBo = new IotHistoryNodeDataBO();
                nodeDataBo.setAtime(new Date());
                nodeDataBo.setNode_id(id);
                nodeDataBo.setSensor_ids(ids.substring(1));
                nodeDataBo.setSdatas(values.substring(1));
                service.insert("IotHistoryNodeData.insert", nodeDataBo);
            }
        } catch (Exception e) {
            exception(e, resultMap, id);
        }
        return getModelAndView(response, resultMap);
    }

    @RequestMapping(method = RequestMethod.GET, value = RequestURLIOT.NodeInfo.NODE_DATA_DOWNLOAD)
    public ModelAndView templateDownload(HttpServletResponse response) {
        String excelName = "设备导入模板";
        Map<String, Object> resultMap = getResultMap();
        try {
            String fileName = URLEncoder.encode(excelName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 获取 ExcelWriter 对象
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                    .excelType(ExcelTypeEnum.XLSX)
                    .build();
            try {
                Method generateExampleMethod = IotNodeInfoBO.class.getMethod("generateExample");
                List<IotNodeInfoBO> exampleList = (List<IotNodeInfoBO>) generateExampleMethod.invoke(null);
                WriteSheet sheet = EasyExcel.writerSheet("设备导入")
                        .head(IotNodeInfoBO.class)
                        .build();
                excelWriter.write(exampleList, sheet);
            } finally {
                // 最终关闭 ExcelWriter
                if (excelWriter != null) {
                    excelWriter.finish();
                }
            }
        } catch (Exception e) {
            return getModelAndView(response, resultMap);
        } finally {
            try {
                response.getOutputStream().flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return getModelAndView(response, resultMap);
    }

    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_DATA_IMPORT)
    public ModelAndView importDevice(HttpServletResponse response, @RequestParam("file") MultipartFile file) {
        Map<String, Object> resultMap = getResultMap();
        DeviceImportListener deviceImportListener = new DeviceImportListener(iotNodeInfoService, dao, resultMap);
        try {
            EasyExcel.read(file.getInputStream(), IotNodeInfoBO.class, deviceImportListener).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
            return getModelAndView(response, resultMap);
        }
        if (deviceImportListener.getErrorList().size() > 0) {
            resultMap.put("data", deviceImportListener.getErrorList());
            resultMap.put("statusMsg", "导入过程中出现数据导入异常，其中成功" + deviceImportListener.getDataList().size() + "条，异常"
                    + deviceImportListener.getErrorList().size() + "条，详情请看响应信息");
            return getModelAndView(response, resultMap);
        } else {
            resultMap.put("statusMsg", "设备导入成功！");
            return getModelAndView(response, resultMap);
        }
    }

    /**
     * 查询用户所属项目下面所有未被他人授权的设备信息
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO_ALL_TO_AUTH)
    public ModelAndView selectAllToAuth(HttpServletResponse response,
                                        @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                        @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            if (obj.getUser_id() == null) {
                UserInfoBO user = getUserInfoByUserKey(userKey);
                obj.setUser_id(user.getId());
            }
            resultMap = service.selectList("IotNodeInfo.selectNodeAllToAuth", obj);

        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 查询用户所属项目下面所有未被他人授权的设备信息
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO_AUTHED)
    public ModelAndView selectAuthed(HttpServletResponse response,
                                     @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                     @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
            if (obj.getUser_id() == null) {
                UserInfoBO user = getUserInfoByUserKey(userKey);
                obj.setUser_id(user.getId());
            }

            resultMap = service.selectList("IotNodeInfo.selectNodeAuthed", obj);

        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }

    /**
     * 保存更新授权
     *
     * @param response
     * @param
     * @return
     */
    @RequestMapping(method = RequestMethod.POST, value = RequestURLIOT.NodeInfo.NODE_INFO_AUTH_UPDATE)
    @Transactional(rollbackFor = Exception.class)
    public ModelAndView updateAuth(HttpServletResponse response,
                                   @RequestHeader(value = ResultMapUtils.USER_KEY, required = true) String userKey,
                                   @RequestBody IotNodeInfoBO obj) {
        Map<String, Object> resultMap = getResultMap();
        try {
			/*UserInfoBO user = getUserInfoByUserKey(userKey);
			if( ! verifyUserRole(userKey, Code.UserType.SUPER) ){
				obj.setUser_id(user.getId());
			}*/

            // 删除当前用户的全部授权
            service.update("IotNodeInfo.deleteAuth", obj);
            if (ObjectUtil.isNotEmpty(obj.getIds())) {
                String[] ids = obj.getIds().split(",");
                for (int i = 0; i < ids.length; i++) {
                    obj.setId(Integer.parseInt(ids[i]));
                    obj.setCustom_id(obj.getUser_id());
                    //添加授权
                    resultMap = service.update("IotNodeInfo.addAuth", obj);
                }
            }

        } catch (Exception e) {
            exception(e, resultMap, obj);
        }
        return getModelAndView(response, resultMap);
    }
}
